
#include "ParticleEmitter.h"
#include "../../Utils/Vector2D.h"
#include "../../Utils/Timer.h"
#include "../../Utils/Util.h"
#include "../TextureManager.h"

#include <cstdlib>


ParticleEmitter::ParticleEmitter(Vector2D emitter_position, Vector2D emit_velocity,
                float emit_rand_min, float emit_rand_max, 
                unsigned particles_per_second,

                float col_r, float col_g, float col_b,
                float life, float life_rand, 
                float size, float size_rand, 
                float life_decay, float life_decay_rand, 
                float size_decay, float size_decay_rand,
                std::string texture, bool flare_up) :
 
    active(true),
    position(emitter_position), emit_velocity(emit_velocity), 
    emit_rand_min(emit_rand_min), emit_rand_max(emit_rand_max),
    particles_per_second(particles_per_second), 
    time_of_last_emit(Timer::currentTicks()),
    particle_col_r(col_r), particle_col_g(col_g), particle_col_b(col_b),
    particle_life(life), particle_life_rand(life_rand), 
    particle_size(size), particle_size_rand(size_rand),
    particle_life_decay(life_decay), particle_life_decay_rand(life_decay_rand),
    particle_size_decay(size_decay), particle_size_decay_rand(size_decay_rand),
    flare_up(flare_up) {

    if(texture.size() > 0){
        use_texturing = true;
        texture_id = TextureManager::instance().loadTexture(texture);
    }
    else{
        use_texturing = false;
        texture_id = 0;
    }

    num_particles_to_emit = 0.0f;
}

ParticleEmitter::~ParticleEmitter(){
}

std::vector<Particle> ParticleEmitter::emit(void){
    float num_particles = ((Timer::currentTicks() - time_of_last_emit)*particles_per_second)/1000.0f;
    num_particles_to_emit += num_particles;
    
    time_of_last_emit = Timer::currentTicks();

    std::vector<Particle> result; 
    if(!active){ return result; }

    for(unsigned i = 0; i < (unsigned)num_particles_to_emit; i++){
        float np_life       = particle_life       + Util::rand_interval(-particle_life_rand, particle_life_rand);
        float np_size       = particle_size       + Util::rand_interval(-particle_size_rand, particle_size_rand);
        float np_life_decay = particle_life_decay + Util::rand_interval(-particle_life_decay_rand, particle_life_decay_rand);
        float np_size_decay = particle_size_decay + Util::rand_interval(-particle_size_decay_rand, particle_size_decay_rand);

        Vector2D vec = Vector2D(Util::rand_interval(-1.0f, 1.0f), 
                                Util::rand_interval(-1.0f, 1.0f));
        while(vec.length() > 1.0f){
            vec = Vector2D(Util::rand_interval(-1.0f, 1.0f), 
                           Util::rand_interval(-1.0f, 1.0f));
        }
        vec.normalise();

        float scale = emit_rand_min + Util::rand_interval(0.0f, 1.0f)*(emit_rand_max - emit_rand_min);
        Vector2D np_velocity = emit_velocity + scale*vec;
       
        Vector2D np_position = position;
        np_position.x += Util::rand_interval(-np_size/8.0f, np_size/8.0f);
        np_position.y += Util::rand_interval(-np_size/8.0f, np_size/8.0f);
 
        Particle new_particle(particle_col_r, particle_col_g, particle_col_b,
                              np_life, np_size, np_life_decay, np_size_decay,
                              np_position, np_velocity, use_texturing, texture_id, flare_up);

        result.push_back(new_particle);
        num_particles_to_emit -= 1.0f;
    }

    return result;
}

void ParticleEmitter::stop(void){ active = false; num_particles_to_emit = 0.0f; }
void ParticleEmitter::start(void){ active = true; }

void ParticleEmitter::setEmitVelocity(Vector2D new_emit_velocity){
    emit_velocity = new_emit_velocity;
}

void ParticleEmitter::setEmitterPosition(Vector2D pos){
    position = pos;
}

